#include "input.h"
#include "vertex.h"

#include <QDebug>
#include <QTextStream>
#include <QStringList>

Input::Input(QFile *_file) : file(_file){
}

Input::Input(){
}

Input::~Input(){
}

Scene *Input::parseIn(){
    int m, n, id;
	double x, y, z;
	Scene* scene = new Scene();
	Object* object;

	QTextStream stream(file);

    stream >> m;

	for(int j = 0; j < m; j++){
        stream >> n;
        object = new Object(scene->nextObjectsID());
        scene->addObject(object);
	    for(int i = 0; i < n; i++){
            stream >> id >> x >> y >> z;
            object->addVertex(new Vertex(id, Point(x, y, z)));
	    }
	}

	return scene;
}

Scene *Input::parseIn(QFile *_file) {
	file = _file;
	return parseIn();
}

Scene *Input::parseOut(){
    int m, n, id, idEdge = 0;
	double x, y, z;
	Scene *scene = new Scene();
	Object *object;
	Face *face;
	Edge *currentE, *prevE, *firstE;
	bool currentESignal, prevESignal, firstESignal;
	Vertex *currentV, *prevV, *firstV;
	QString string;
	QStringList faceVertices;

	QTextStream stream(file);

    stream >> m;

	for(int j = 0; j < m; j++){
        stream >> n;
        object = new Object(scene->nextObjectsID());
        object->setConvexHull(true);
        scene->addObject(object);

	    for(int i = 0; i < n; i++){
            stream >> id >> x >> y >> z;
            object->addVertex(new Vertex(id, Point(x, y, z)));
	    }

        stream >> n;
	    for(int i = 0; i < n; i++){
            if(i == 0) string = stream.readLine();
            string = stream.readLine();
            faceVertices = string.split(" ");

            firstV = object->getVertexById(faceVertices.at(1).toInt());
            prevV = object->getVertexById(faceVertices.at(2).toInt());

            firstE = new Edge(idEdge++, firstV, prevV);
            firstESignal = object->addEdge(&firstE);
            prevE = firstE;
            prevESignal = firstESignal;

            face = new Face(faceVertices.at(0).toInt(), object, firstE, firstESignal);
            object->addFace(face);

            firstV->setEdge(firstE, firstESignal);
            if(firstESignal){
                firstE->setClockwise(face);
            }else{
                firstE->setCounterClockwise(face);
            }

            for(int k = 3; k < faceVertices.size(); k++){
                currentV = object->getVertexById(faceVertices.at(k).toInt());

                currentE = new Edge(idEdge++, prevV, currentV);
                currentESignal = object->addEdge(&currentE);
                prevV->setEdge(currentE, currentESignal);

                if(currentESignal){
                    currentE->setClockwise(face);
                    currentE->setPreviousClockwise(prevE, prevESignal);
                }else{
                    currentE->setCounterClockwise(face);
                    currentE->setPreviousCounterClockwise(prevE, prevESignal);
                }

                if(prevESignal){
                    prevE->setNextClockwise(currentE, currentESignal);
                }else{
                    prevE->setNextCounterClockwise(currentE, currentESignal);
                }

                prevV = currentV;
                prevE = currentE;
                prevESignal = currentESignal;
            }
            currentE = new Edge(idEdge++, prevV, firstV);
            currentESignal = object->addEdge(&currentE);
            prevV->setEdge(currentE, currentESignal);

            if(currentESignal){
                currentE->setClockwise(face);
                currentE->setPreviousClockwise(prevE, prevESignal);
                currentE->setNextClockwise(firstE, firstESignal);
            }else{
                currentE->setCounterClockwise(face);
                currentE->setPreviousCounterClockwise(prevE, prevESignal);
                currentE->setNextCounterClockwise(firstE, firstESignal);
            }

            if(prevESignal){
                prevE->setNextClockwise(currentE, currentESignal);
            }else{
                prevE->setNextCounterClockwise(currentE, currentESignal);
            }

            if(firstESignal){
                firstE->setPreviousClockwise(currentE, currentESignal);
            }else{
                firstE->setPreviousCounterClockwise(currentE, currentESignal);
            }


	    }
	}

	return scene;
}

Scene *Input::parseOut(QFile *_file) {
	file = _file;
	return parseOut();
}

Scene *Input::parseScene(){
	char type;
	double x, y, z;
	Scene* scene = new Scene();
	Object* object = new Object(scene->nextObjectsID());
    scene->addObject(object);

	QTextStream stream(file);

	while(stream >> type, !stream.atEnd()) {
		if(type == 'v') {
            stream >> x >> y >> z;
            object->addVertex(new Vertex(scene->nextVerticesID(), Point(x, y, z)));
//            if(!object->haveConvexHull()){
//                stream >> x >> y >> z;
//                object->addVertex(new Vertex(object->nextID(), Point(x, y, z)));
//            }else{
//                stream >> id >> x >> y >> z;
//                object->addVertex(new Vertex(id, Point(x, y, z), ));
//            }
			continue;
		} else if(type == '-') {
		    object = new Object(scene->nextObjectsID());
		    scene->addObject(object);
			continue;
		} else if(type == '#') {
			//Comments!
			stream.readLine();
			continue;
		}
	}
	return scene;
}

Scene *Input::parseScene(QFile *_file) {
	file = _file;
	return parseScene();
}

Object *Input::parseObject(Scene *_s){
	char type;
	double x, y, z;
	Object* object = new Object(_s->nextObjectsID());
    _s->addObject(object);

	QTextStream stream(file);

	while(stream >> type, !stream.atEnd()) {
		if(type == 'v') {
			stream >> x >> y >> z;
			object->addVertex(new Vertex(_s->nextVerticesID(), Point(x, y, z)));
			continue;
		} else if(type == '#') {
			//Comments!
			stream.readLine();
			continue;
		}
	}
	return object;
}

Object *Input::parseObject(QFile *_file, Scene *_s){
	file = _file;
	return parseObject(_s);
}
